package com.hopu.springbootdemo2.config;

import com.alibaba.fastjson2.JSON;
import com.hopu.springbootdemo2.filter.TokenAuthenticationFilter;
import com.hopu.springbootdemo2.handler.LoginSuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.annotation.Resource;
import java.util.Arrays;

/**
 * SpringSecurity的配置
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        prePostEnabled = true,
        securedEnabled = true,
        jsr250Enabled = true)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //提供密码加密器
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Resource
    private UserDetailsService userDetailsService;

    //验证配置
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //设置登录验证的逻辑
        auth.userDetailsService(userDetailsService);
    }

    //授权配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        //设置访问控制
//        http.authorizeRequests()
//                .antMatchers("/sjsp").hasAuthority("上架商品")
//                .antMatchers("/sccg").hasAnyRole("总经理","管理员","主管");

        http.authorizeRequests()
                .antMatchers("/user/login","/upload")
                .permitAll()                                     //配置请求验证白名单
                .anyRequest()
                .authenticated()                                 //其它的所有请求要求验证
                .and()
                .formLogin()                                     //登录相关的配置
                .loginProcessingUrl("/user/login")               //登录处理的url
                .successHandler(new LoginSuccessHandler())       //登录成功处理器
                .failureHandler((req,resp,e) -> {                //登录失败处理器
                    ResponseEntity<String> entity = ResponseEntity.ok("login failed");
                    resp.getWriter().write(JSON.toJSONString(entity));
                })
                .and()
                .logout()                                        //登出相关的配置
                .logoutUrl("/user/logout")
                .logoutSuccessHandler((req,resp,e) -> {          //登出成功处理器
                    ResponseEntity<String> entity = ResponseEntity.ok("logout success");
                    resp.getWriter().write(JSON.toJSONString(entity));
                })
                .clearAuthentication(true)                       //登出后请求验证信息
                .and()
                .exceptionHandling()                             //全局异常处理
                .authenticationEntryPoint((req,resp,e) -> {      //没有通过token验证执行的逻辑
                    ResponseEntity<String> entity = ResponseEntity.ok("not login");
                    resp.getWriter().write(JSON.toJSONString(entity));
                })
                .and()
                .csrf().disable()                                 //禁用csrf保护
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS) //session设置为无状态
                .and()
                .cors()                                           //跨域配置
                .configurationSource(corsConfigurationSource())   //配置跨域源
                .and()
                .addFilter(new TokenAuthenticationFilter(authenticationManager()));  //配置过滤器                               //配置token验证过滤器
    }

    /**
     * 创建跨域源对象
     * @return
     */
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        //配置允许访问的服务器域名
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
